<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Language" content="en" />
    <title>skalibs: the ip46 library interface</title>
    <meta name="Description" content="skalibs: the ip46 library interface" />
    <meta name="Keywords" content="skalibs c unix ip46 library libstddjb" />
    <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
  </head>
<body>

<p>
<a href="index.html">libstddjb</a><br />
<a href="../libskarnet.html">libskarnet</a><br />
<a href="../index.html">skalibs</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>

<h1> The <tt>ip46</tt> library interface </h1>

<p>
 The following functions and structures are declared in the <tt>skalibs/ip46.h</tt> header,
and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library.
</p>

<h2> General information </h2>

<p>
 <tt>ip46</tt> is a set of macros and functions to support both IPv4
and IPv6 network operations in an abstracted way.
</p>

<p>
 If skalibs has been built with the <a href="../flags.html#noipv6">--disable-ipv6</a>
configure option, or it detects at build time than the target does not support IPv6, then
<tt>ip46</tt> structures and functions will be directly aliased to their
IPv4 implementations with no overhead at all.
</p>

<h2> Data structures </h2>

<p>
 An <tt>ip46full_t</tt> is a structure that contains either an IPv4 or an IPv6
address.
 If <em>a</em> is an <tt>ip46full_t</tt>, then:
</p>

<ul>
 <li> ip46_is6(&amp;<em>a</em>) is 1 if <em>a</em> is
IPv6 and 0 otherwise. </li>
 <li> <em>a</em>.ip points to 16 (if IPv6) or 4 (if IPv4) bytes containing
the address, in network byte order. </li>
</ul>

<p>
 If skalibs has been build with IPv6 support, an <tt>ip46_t</tt> is
the same type as an <tt>ip46full_t</tt>. Otherwise, an <tt>ip46_t</tt>
is a structure that just contains an IPv4 address.
</p>

<h2> Functions </h2>

<p>
<code> int ip46_from_ip4 (ip46_t *a, char const *ip) </code> <br />
Stores the IPv4 pointed to by <em>ip</em> into *<em>a</em>. Returns 1.
</p>

<p>
<code> int ip46_from_ip6 (ip46_t *a, char const *ip) </code> <br />
Stores the IPv6 pointed to by <em>ip</em> into *<em>a</em>. Returns 1,
except if IPv6 is unavailable, in which case it returns 0 ENOSYS.
</p>

<p>
<code> size_t ip46_fmt (char *s, ip46_t const *a) </code> <br />
Formats the address in *<em>a</em> into the string <em>s</em>, which
must be preallocated. Returns the number of bytes written. The address
will be accordingly formatted as IPv4 or IPv6.
</p>

<p>
<code> size_t ip46_scan (char const *s, ip46_t *a) </code> <br />
Scans the string <em>s</em> for an IPv4 or IPv6 address. If it finds
one, writes it into *<em>a</em> and returns the number of bytes read.
If it cannot, returns 0.
</p>

<p>
<code> size_t ip46_scanlist (ip46_t *list, size_t max, char const *s, size_t *n) </code> <br />
Scans the string <em>s</em> for a list of comma-, semicolon-, space-, tab- or
newline-separated IPv4 or IPv6 addresses, up to a maximum of <em>max</em>. It
stores them into the (preallocated) ip46_t array pointed to by <em>list</em>.
It returns the number of bytes read (0 if <em>s</em> does not contain a valid
IP list at all), and stores the number of found and scanned addresses into *<em>n</em>.
</p>

<p>
<code> int socket_connect46 (int fd, ip46_t *a, uint16_t port) </code> <br />
Connects the socket <em>fd</em> to address *<em>a</em> and port <em>port</em>.
Returns 0 in case of success, and -1 (and sets errno) in case of failure.
</p>

<p>
<code> int socket_bind46 (int fd, ip46_t *a, uint16_t port) </code> <br />
Binds the socket <em>fd</em> to address *<em>a</em> and port <em>port</em>.
Returns 0 in case of success, and -1 (and sets errno) in case of failure.
</p>

<p>
<code> int socket_bind46_reuse (int fd, ip46_t *a, uint16_t port) </code> <br />
Same as the previous function, with the SO_REUSEADDR option.
</p>

<p>
<code> int socket_deadlineconnstamp46 (int fd, ip46_t const *a, uint16_t port, tain_t const *deadline, tain_t *stamp) </code> <br />
Attempts to synchronously connect the socket <em>fd</em> to address a<em>a</em>
and port <em>port</em>. Returns 1 if it succeeds and 0 (and sets errno)
if it fails. <em>stamp</em> must contain an accurate enough
timestamp, and is updated when the function returns. If the connection is
still pending by <em>deadline</em>, then the attempt stops and the function
returns 0 ETIMEDOUT.
</p>

<p>
<code> ssize_t socket_recv46 (int fd, char *s, size_t len, ip46_t *a, uint16_t *port) </code> <br />
Reads a datagram from socket <em>fd</em>. The message is stored into buffer <em>s</em>
of max length <em>len</em>, and stores the sender information into address *<em>a</em>
and port *<em>port</em>. Returns the length of the read datagram, or -1 if it fails.
</p>

<p>
<code> ssize_t socket_send46 (int fd, char const *s, size_t len, ip46_t const *a, uint16_t port) </code> <br />
Writes a datagram to socket <em>fd</em>. The message is read from buffer <em>s</em>
of length <em>len</em>, and the recipient information is address *<em>a</em>
and port <em>port</em>. Returns the number of written bytes, or -1 if it fails.
</p>

<p>
<code> int socket_local46 (int fd, ip46_t *a, uint16_t *port) </code> <br />
Gets the local information about bound socket <em>fd</em>: the local IP
address is stored into *<em>a</em> and the local port into *<em>port</em>.
Returns 0 in case of success, and -1 (and sets errno) in case of failure.
</p>

<p>
<code> int socket_remote46 (int fd, ip46_t *a, uint16_t *port) </code> <br />
Gets the peer information about connected socket <em>fd</em>: the remote IP
address is stored into *<em>a</em> and the remote port into *<em>port</em>.
Returns 0 in case of success, and -1 (and sets errno) in case of failure.
</p>

<p>
<code> ssize_t socket_recvnb46 (int fd, char *s, size_t len, ip46_t *a, uint16_t *port,
tain_t const *deadline, tain_t *stamp) </code> <br />
Like <tt>socket_recv46</tt>, except that the function blocks until a datagram
is received. *<em>stamp</em> must be an accurate enough approximation of the
current time, and is updated when the function returns. If no datagram has
arrived by absolute date *<em>deadline</em>, the function returns -1 ETIMEOUT.
</p>

<p>
<code> ssize_t socket_sendnb46 (int fd, char const *s, size_t len, ip46_t const *a, uint16_t port,
tain_t const *deadline, tain_t *stamp) </code> <br />
Like <tt>socket_send46</tt>, except that the function blocks until a datagram
has been effectively sent. *<em>stamp</em> must be an accurate enough approximation of the
current time, and is updated when the function returns. If the message still has
not been sent by absolute date *<em>deadline</em>, the function returns -1 ETIMEOUT.
</p>

</body>
</html>
